package glapp;


import org.lwjgl.opengl.*;
import org.lwjgl.input.*;
import org.lwjgl.util.glu.*;

import test.CubeGl;
import glapp.*;
import glmodel.*;

/**
 * Load and render an OBJ file. Demonstrate simple navigation by moving the
 * gluLookat() viewpoint with the arrow keys.
 * <P>
 * Use GLModel to load the mesh and render it with texture and lighting.
 * <P>
 * GLApp initializes the LWJGL environment for OpenGL rendering, ie. creates a
 * window, sets the display mode, inits mouse and keyboard, then runs a loop
 * that calls draw().
 * <P>
 * napier at potatoland dot org
 */
public class GLApp_DemoModel extends GLApp {
	// Model will be loaded from 3DS file
	GLModel object;
	GLImage sky;
	CubeGl tile;
	// Light direction: if last value is 0, then this describes light direction.
	// If 1, then light position.
	float lightDirection[] = { -2f, 2f, 2f, 0f };
	// Camera position
	static float[] cameraPos = { 0f, 4f, 35f };
	float cameraRotation = 0f;
	// A constant used in navigation
	final float piover180 = 0.0174532925f;
	
	float ccx = 0f, ccy = 0f, ccz = 0f;

	float rotation = 0;

	/**
	 * Start the application. demo.run() calls setup(), handles mouse and
	 * keyboard input, and calls draw() in a loop.
	 */
	public static void main(String args[]) {
		GLApp_DemoModel demo = new GLApp_DemoModel();
		demo.window_title = "GLApp Demo Model";
		demo.displayWidth = 800;
		demo.displayHeight = 600;
		demo.run();
	}

	/**
	 * Initialize the scene. Called by GLApp.run()
	 */
	public void setup() {
		// enable lighting and texture rendering
		GL11.glEnable(GL11.GL_LIGHTING);
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		GL11.glClearColor(.5f, .6f, .9f, 1f);

		// setup and enable perspective
		setPerspective();

		// Create a light
		setLight(GL11.GL_LIGHT1, new float[] { 1f, 1f, 1f, 1f }, // diffuse
																	// color
				new float[] { .6f, .6f, .9f, 1f }, // ambient
				new float[] { 1f, 1f, 1f, 1f }, // specular
				lightDirection); // direction/position

		setAmbientLight(new float[] { .6f, .6f, .9f, 1f });

		sky = loadImage("images/sky.jpg");

		// Load the model
		object = new GLModel("models/BMW/bmw_full.obj");
		object.regenerateNormals();
		tile = new CubeGl(new float[]{20f,10f,20f}, new float[]{0.58f,0.58f,0.58f,1.0f,0.2f}, "images/pavement1.jpg");
	}

	/**
	 * Render one frame. Called by GLApp.run().
	 */
	public void render() {
		// use the frames per second to animate
		rotation += 25f * getSecondsPerFrame();
		
		// clear depth buffer and color
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

		// draw background image
		drawImageFullScreen(sky);

		// adjust camera position according to arrow key events
		setCameraPosition();

		// select model view and reset
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();

		
		GLU.gluLookAt(
				cameraPos[0],
				cameraPos[1],
				cameraPos[2], // where is the eye
				// look at a point directly in front of camera
				cameraPos[0] - (float) Math.sin(cameraRotation * piover180),
				cameraPos[1],
				cameraPos[2] - (float) Math.cos(cameraRotation * piover180),
				// cameraPos[0]-(float)Math.sin(ccx * piover180), cameraPos[1],
				// cameraPos[2]- (float) Math.cos(cameraRotation* piover180),
				0f, 1f, 0f); // which way is up

		// draw object at center
		//camrot();
		GL11.glPushMatrix();
		{
			GL11.glRotatef(rotation, 0, 1, 0); // turn it
			//GL11.glRotatef(-90f, 1f, 0, 0);
			GL11.glScalef(1f, 1f, 1f);
			//object.render();
			tile.render();
		}
		GL11.glPopMatrix();

		// Place the light. Light will move with the rest of the scene
		setLightPosition(GL11.GL_LIGHT1, lightDirection);
	}

	/**
	 * set the field of view and view depth.
	 */
	public static void setPerspective() {
		// select projection matrix (controls perspective)
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		// fovy, aspect ratio, zNear, zFar
		GLU.gluPerspective(40f, // zoom in or out of view
				aspectRatio, // shape of viewport rectangle (width/height)
				.1f, // Min Z: how far from eye position does view start
				500f); // max Z: how far from eye position does view extend
		// return to modelview matrix
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
	}

	/**
	 * Adjust the Camera position based on keyboard arrow key input.
	 */
	public void setCameraPosition() {
		// Turn left
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
			cameraRotation += 1.0f;
		}
		// Turn right
		if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
			cameraRotation -= 1.0f;
		}
		// move forward in current direction
		if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
			cameraPos[0] -= (float) Math.sin(cameraRotation * piover180) * .5f;
			cameraPos[2] -= (float) Math.cos(cameraRotation * piover180) * .5f;
		}
		// move backward in current direction
		if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
			cameraPos[0] += (float) Math.sin(cameraRotation * piover180) * .5f;
			cameraPos[2] += (float) Math.cos(cameraRotation * piover180) * .5f;
		}
		// move camera down
		if (Keyboard.isKeyDown(Keyboard.KEY_PRIOR)) {
			cameraPos[1] += .13f;
		}
		// move camera up
		if (Keyboard.isKeyDown(Keyboard.KEY_NEXT)) {
			cameraPos[1] -= .13f;
		}
	}

	boolean isMouseDown = false;
	int mclickx = 0, mclicky = 0;

	public void mouseMove(int x, int y) {
		if (isMouseDown) {
			if (x > mclickx) {
				ccx += 1.0f;
				if (ccx > 360.0f) ccx -= 360.0f;
			} else {
				ccx -= 1.0f;
				if (ccx < 0.0f) ccx += 360.0f;
			}
			mclickx = x;

		}

	}

	public void mouseDown(int x, int y) {
		isMouseDown = true;
		mclickx = x;
		mclicky = y;

	}

	public void mouseUp(int x, int y) {
		isMouseDown = false;
	}

	public void keyDown(int keycode) {
	}

	public void keyUp(int keycode) {
	}
	public void camrot(){
		GL11.glRotatef(ccx,1.0f,0.0f,0.0f);  //rotate our camera on teh x-axis (left and right)
		GL11.glTranslatef(cameraPos[0],cameraPos[1],cameraPos[2]);
	}
}